/*
 *  logutil.c
 *
 *  Copyright (C) 2011  Peter Polacik <polacik.p@gmx.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "alogd.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

/*
 * get_msg: Reads message from socket
 *
 * 	Returns realloc(3) allocated buffer, containing whole message
 */

#ifndef MSG_BUF_LOW
#define MSG_BUF_LOW 64
#endif

char *get_msg(int sfd)
{
	char *ret;
	int size = 0, count = 0;
	char c;
	ret = (char *)malloc(MSG_BUF_LOW);
	size = MSG_BUF_LOW;
	if (ret == NULL)
		errorize("get_msg:initial alloc", E_ALLOC);
	while (read(sfd, &c, sizeof(char)) > 0) {
		count++;
		if (count >= size) {
			size <<= 1;
			ret = (char *)realloc(ret, size);
			if (ret == NULL)
				errorize("get_msg:realloc", E_ALLOC);
		}
		if (c == EOM) {
			ret[count - 1] = '\0';
			break;
		} else ret[count - 1] = c;
	}
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] get_msg:ret @ %p \'%s\'\n", ret, ret);
#endif
	return ret;
}

/*
 * parse_msg: Divides message string received from client to logical parts
 *
 * 	Returns structure, which contains actual parts of buf:
 * 		program name, type of message to log, message itself
 *
 * 	Message format:
 * 		ALOGD MSG BEGIN (keywords)
 * 		<program_name>
 * 		<msg_type:integer>
 * 		<msg_body>
 * 		<EOM == ETB (end of transmission block, 0x17 in ASCII)>
 * 			EOM is replaced with NUL in get_msg
 */

mesg_t *parse_msg(char *buf, int len)
{
	mesg_t *ret;
	char *pname, *tmp, *tmp2;
	unsigned is_msg;
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] buf (%d) @ %p : \'%s\'\n", len, buf, buf);
#endif
	/* First, we allocate return value */
	ret = (mesg_t *)malloc(sizeof(mesg_t));
	if (ret == NULL)
		return NULL;
	/* Then, we discover whether it really is message */
	tmp2 = buf;
	if (!strcmp(strsep(&buf, " "), "ALOGD")) {
		if (!strcmp(strsep(&buf, " "), "MSG")) {
			if (!strcmp(strsep(&buf, " "), "BEGIN"))
				is_msg = 1;
		}
	}
	if (!is_msg) {
		ret->progname = "dummy";
		ret->type = T_DEFAULT;
		ret->msg = "No valid message found";
		return ret;
	}
	/* Then, we extract program name */
	pname = strsep(&buf, " ");
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] pname @ %p : \'%s\'\n", pname, pname);
#endif
	ret->progname = fixname(pname, 'x');
	if (strlen(pname) >= (unsigned int) len) {
		ret->type = T_DEFAULT;
		ret->msg = "NO MESSAGE";
	} else {
		tmp = strsep(&buf, " ");
		if (buf != NULL) {
			sscanf(tmp, "%d", &(ret->type));
			ret->msg = buf;
		} else {
			ret->msg = tmp;
			ret->type = T_DEFAULT;
		}
	}
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] type : %d\n", ret->type);
	fprintf(stderr, "[DEBUG] msg @ %p : \'%s\'\n", ret->msg, ret->msg);
#endif
	buf = tmp2;
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] buf @ %p\n", buf);
#endif
	return ret;
}

/*
 * getmsghdr: Returns string characterized by type number
 *
 * 	TODO: Possibly add features like definition of own headers etc.
 */

char *getmsghdr(int type)
{
	switch (type) {
		case T_FERR : return "\n[FATAL]\n";
			break;
		case T_ERR : return "\n[ERROR]\n";
			break;
		case T_WARN : return "\n[WARNING]\n";
			break;
		case T_INFO : return "\n[INFO]\n";
			break;
		case T_DEBUG : return "\n[DEBUG]\n";
			break;
		default : return "\n[???]\n";
	}
	return "\n[???]\n";
}

/*
 * program_log: Actually writes message to file
 *
 * 	Arguments: file descriptor, message header, message body, flags
 * 	Flags: OR-ed values of different macros defined in logging.h
 * 		Currently there are NONE (0)
 * 	Returns: 0 on success
 * 		 1 if there are some unsupported flags set
 */
int program_log(int fd, char *hdr, char *msg, int flags)
{
	int ret = 0;
	if (flags != 0)
		ret = 1;
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] hdr @ %p : \'%s\'\n", hdr, hdr);
#endif
	if (write(fd, hdr, strlen(hdr)) == -1)
		fprintf(stderr, "[WARNING] Writing to file: %s\n",
			strerror(errno));
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] msg @ %p : \'%s\'\n", msg, msg);
#endif
	if (write(fd, msg, strlen(msg)) == -1)
		fprintf(stderr, "[WARNING] Writing to file: %s\n",
			strerror(errno));
	return ret;
}
